package squareBorderPackage;

import java.math.BigDecimal;

import java.util.*;

import temperaturePackage.*;

import be.kuleuven.cs.som.annotate.*;

/**
 * A class of rock squares.
 * 
 * @version 1.0
 * @author Jessa Bekker & Esther Alberts
 */
public class RockSquare extends Square {
	
	/**
	 * Initialize a new RockSquare with six walls.
	 */
	public RockSquare(){
		super(true, Direction.FLOOR, 
				Direction.CEILING, Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH);
	}
	
	/**
	 * Check whether there is a wall in every direction of this square.
	 * 
	 * return	False if the
	 */
	public boolean hasOnlyWalls (HashMap<Direction, Border> borders){
		for(Border border : borders.values())
			if(!(border instanceof Wall))
				return false;
		return true;
	}
	
	/**
	 * Check whether the given borders are appropriate borders
	 * 
	 * @return 	False if the given borders are not all walls.
	 * 			| if(hasOnlyWalls(borders))
	 * 			|	then (result == false) 	
	 */
	@Override
	public boolean areAppropriateBorders (HashMap<Direction, Border> borders) {
		return (super.areAppropriateBorders(borders)
			&& hasOnlyWalls(borders));
	}
	
	/**
	 * Return whether there is an obstacle in the given direction.
	 * 
	 * @return	This RockSquare has obstacles in every direction.
	 * 			|result==true
	 */
	@Override
	public final boolean getObstacleAt(Direction direction){
		return true;
	}
	
	/**
	 * Return the number of squares in the space of this RockSquare.
	 * 
	 * @return 	the number of squares in the space of this RockSquare is equal to 1.
	 * 			|result == 1
	 */
	@Override
	public final int getNbOfSquaresInSpace(){
		return 1;
	}
	
	/**
	 * Return a set containing all the squares that are in the space of this square.
	 */
	@Override
	public Set<? extends Square> getSpace() {
		if(isTerminated())
			return null;
		Set<Square> space = new HashSet<Square>();
		space.add(this);
		return space;
	}
	
	
	/**
	 * Update the space of this square.
	 */
	@Override
	public void updateSpace() {
	}
	
	/**
	 * Get all the temperatures of the squares tangent to this RockSquare.
	 */
	private ArrayList<Double> getNeighborTemperatures(){
		
		ArrayList<Double> neighborTemperatures = new ArrayList<Double>();
		
		for(Direction direction:this.getBorders().keySet()){
			Square neighborSquare = this.getBorderAt(direction).getSquareAt(direction.getOpposite());
			
			//Set all temperatures of squares tangent to this rock square in a list
			if(neighborSquare != null && !(neighborSquare instanceof RockSquare)){
				Double temperatureNeighborSquare 
						= neighborSquare.getTemperature().toUnit(TemperatureUnit.CELSIUS).getNumeral();
				neighborTemperatures.add(temperatureNeighborSquare);
			}
		}
		return neighborTemperatures;
	}
	
	/**
	 * Return the temperature of this rock square.
	 */
	@Override
	public Temperature getTemperature(){
		
		double sumOfTemperatures = (double) 0;
		int nbOfNeighbors = 0;
		
		//Calculate the sum of all temperatures from the squares tangent to this square.
		//Count the number of squares tangent to this square.
		for(Double temperature : getNeighborTemperatures()){
			sumOfTemperatures += temperature;
			nbOfNeighbors++;
		}
		double newTemperatureNumeral;
		
		//if this rock square has no neighbors, its temperature is zero celsius degrees.
		if(nbOfNeighbors == 0)
			newTemperatureNumeral = 0;
		//Else: calculate the new temperature of this square
		else
			newTemperatureNumeral = sumOfTemperatures/nbOfNeighbors;
		
		return new Temperature(newTemperatureNumeral,TemperatureUnit.CELSIUS);
	}
	
	/**
	 * Return the humidity of this rock square.
	 */
	@Override
	public BigDecimal getHumidity() {
		return BigDecimal.ZERO;
	}

	/**
	 * Returns the rust damage of this square. The rust damage is a rate of how
	 * much metal objects in this square are damaged by rust.
	 * 
	 * @return	The rustDamage of this square is always zero.
	 * 			| result == 0
	 */
	@Raw @Override
	public int getRustDamage() {
		return 0;
	}

}
